package com.tool.genxml.entity;

import cn.hutool.core.text.CharSequenceUtil;
import com.tool.genxml.emum.AttrEnum;
import lombok.Data;
import lombok.ToString;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;

import java.util.Objects;

import static com.tool.genxml.constant.SysConstant.*;

@Data
@ToString
public class XRow {

    /**
     * 当前行原始Excel信息
     */
    private XSSFRow row;

    /**
     * 节点等级
     */
    private int level = -1;

    /**
     * 注释
     */
    private String notes = "";

    /**
     * 节点名，即报文要素
     */
    private String name = "Element";

    /**
     * 节点符号
     */
    private String tag = "Element";

    private String value = "str";

    /**
     * 记录当前节点是Excel表中第几行
     */
    private int index;

    /**
     * 当前节点的xpath
     */
    private String xPath;

    /**
     * 父节点的xpath
     */
    private String parentPath;

    /**
     * 是否为循环域
     * 1...n
     */
    private boolean cyclic;

    /**
     * 是否需要签名
     */
    private boolean sign;

    /**
     * 属性字段
     */
    private String attrName;

    /**
     * 是否为属性
     */
    private boolean isAttr;

    /**
     * 是否含有属性
     */
    private boolean hasAttr;

    /**
     * 最小循环次数
     */
    private int minOccurs;

    /**
     * 最大循环次数，当次数为n时该值为-1
     */
    private int maxOccurs;

    /**
     * 是否存在组件
     */
    private boolean hasComponent;

    /**
     * 组件名
     */
    private String componentName;

    public XRow() {
    }

    public XRow(XSSFRow row) {
        this.row = row;

        // 报文要素
        setOriginName(row.getCell(2));

        // tag
        setOriginTag(row.getCell(3));

        // 循环次数
        setOccurs(row.getCell(6));

        // 数据类型，有可能写的是组件类型
        setDataType(row.getCell(7));

        // 备注，如果其中写的是组件类型
        setMark(row.getCell(8));

        // 是否是加签要素
        setOriginSign(row.getCell(9));

        // 为节点赋值
        setOriginVal(row.getCell(10));

        this.value = DEFAULT_VAL;
    }

    public static XRow of(XSSFRow row) {
        try {
            return new XRow(row);
        } catch (Exception e) {
            System.out.println("sheet行转化对象报错，行数为: " + row.getRowNum() + ", sheet页为: " + row.getSheet().getSheetName());
            throw e;
        }
    }

    public void setOriginSign(XSSFCell sign) {
        if (Objects.nonNull(sign)) {
            setOriginSign(sign.toString());
        }
    }
    public void setOriginSign(String signStr) {
        if (CharSequenceUtil.isBlank(signStr)) {
            return;
        }

        if (Objects.equals(TICK, signStr.trim())) {
            this.sign = true;
        }
    }

    /**
     * 为节点赋值
     * @param val
     */
    public void setOriginVal(XSSFCell val) {
        if (Objects.nonNull(val)) {
            String value = val.toString();
            if (CharSequenceUtil.isNotBlank(value)) {
                setValue(value);
            }
        }
    }

    public void setDataType(XSSFCell dataType) {
        if (Objects.nonNull(dataType)) {
            setDataType(dataType.toString());
        }
    }

    /**
     * 数据类型列可能是真实的xml数据类型，也可能是组件类型
     * 组件类型: 【接入机构组件】
     * @param dataType
     */
    public void setDataType(String dataType) {
        if (CharSequenceUtil.isBlank(dataType)) {
            return;
        }

        dataType = dataType.trim();

        if (dataType.startsWith(LEFT_BOLD_BRACKET)) {
            setMark(dataType);
            return;
        }

        AttrEnum attr = AttrEnum.exit(dataType);
        if (Objects.nonNull(attr)) {
            AttrType attrType = attr.getAttrType();
            this.attrName = attrType.getAttr();
            this.hasAttr = true;
        }
    }

    public void setMark(XSSFCell mark) {
        if (Objects.nonNull(mark)) {
            setMark(mark.toString());
        }
    }
    /**
     * 当其中写的是组件类型时
     * @param mark
     */
    public void setMark(String mark) {
        if (CharSequenceUtil.isBlank(mark)) {
            return;
        }

        mark = mark.trim();

        if (mark.contains(LEFT_BOLD_BRACKET)) {
            this.hasComponent = true;
            this.componentName = mark.substring(mark.indexOf(LEFT_BOLD_BRACKET) + 1,
                    mark.indexOf(RIGHT_BOLD_BRACKET));
        }
    }

    public void setOccurs(XSSFCell occurs) {
        if (Objects.nonNull(occurs)) {
            setOccurs(occurs.toString());
        }
    }
    /**
     * 设置最大最小循环次数， 当最大循环次数为n时设置为-1
     * [1..1][1..n]
     * @param occurs
     */
    public void setOccurs(String occurs) {
        if (CharSequenceUtil.isBlank(occurs)) {
            return;
        }

        occurs = occurs.trim();

        String minStr = occurs.substring(1, occurs.indexOf(DOT));
        String maxStr = occurs.substring(occurs.lastIndexOf(DOT) + 1, occurs.indexOf(RIGHT_BRACKET));

        this.minOccurs = Integer.parseInt(minStr);
        this.maxOccurs = (Objects.equals(MAX_N, maxStr) || Objects.equals(MAX_N_2, maxStr)) ? -1 : Integer.parseInt(maxStr);
        this.cyclic = judgeCyclic();
    }

    public void setOriginTag(XSSFCell tags) {
        if (Objects.nonNull(tags)) {
            setOriginTag(tags.toString());
        }
    }
    /**
     * 设置节点tag
     * <PrtryData>需要出去前后的尖括号
     * @param tags
     */
    public void setOriginTag(String tags) {
        tags = tags.trim();
        this.tag = tags.substring(1, tags.length() - 1);
    }

    public void setOriginName(XSSFCell nodeNameCell) {
        if (Objects.nonNull(nodeNameCell)) {
            setOriginName(nodeNameCell.toString());
        }
    }

    /**
     * 设置节点名
     * --MessageIdentification
     * 根据前面的横杆设置节点等级，如果是Message root时，将等级设为-1
     * @param nodeName
     */
    public void setOriginName(String nodeName) {
        nodeName = nodeName.trim();
        if (Objects.equals(nodeName, MESSAGE_ROOT)) {
            this.level = -1;
        } else {
            int i = nodeName.lastIndexOf(DASH);
            this.level = i + 1;
        }

        int subIndex = this.level == -1 ? 0 : this.level;
        this.name = nodeName.substring(subIndex);
    }

    /**
     * 判断是否为循环域
     * @return
     */
    public boolean judgeCyclic() {
        return this.maxOccurs > 1 || this.maxOccurs == -1;
    }

    /**
     * 判断是否为循环域
     * @return
     */
    public boolean isCyclic() {
        return cyclic;
    }


}
